package com.wudeyong;

import java.io.*;
import java.util.*;

/**
 * Author :wudeyong
 * Date 2017/7/3
 * For More Information,Please Visit https://wudeyong.com
 */
public class ClusterCalculate {

//    空间中的数据点
    ArrayList<DataPoint> dataPoints = new ArrayList<DataPoint>();

    public List<Cluster> startAnalysis(List<DataPoint> dataPoints, int ClusterNum){
        List<Cluster> finalClusters=new ArrayList<Cluster>();

        List<Cluster> originalClusters=initialCluster(dataPoints);
        finalClusters=originalClusters;
        while(finalClusters.size()>ClusterNum){
            double min=Double.MAX_VALUE;
            int mergeIndexA=0;
            int mergeIndexB=0;
            for(int i=0;i<finalClusters.size();i++){
                for(int j=0;j<finalClusters.size();j++){
                    if(i!=j){
                        Cluster clusterA=finalClusters.get(i);
                        Cluster clusterB=finalClusters.get(j);
                        List<DataPoint> dataPointsA=clusterA.getDataPoints();
                        List<DataPoint> dataPointsB=clusterB.getDataPoints();
                        for (DataPoint aDataPointsA : dataPointsA) {
                            for (DataPoint aDataPointsB : dataPointsB) {
                                double tempDis = getDistance(aDataPointsA, aDataPointsB);
                                if (tempDis < min) {
//                                    找到的最小距离
                                    min = tempDis;
                                    mergeIndexA = i;
                                    mergeIndexB = j;
                                }
                            }
                        }
                    }
                } //end for j
            }// end for i
            //合并cluster[mergeIndexA]和cluster[mergeIndexB]
            finalClusters=mergeCluster(finalClusters,mergeIndexA,mergeIndexB);
        }//end while
        return finalClusters;
    }
    private List<Cluster> mergeCluster(List<Cluster> clusters,int a,int b){
        if (a != b) {
            // 将cluster[b]中的DataPoint加入到 cluster[a]
            Cluster clusterA = clusters.get(a);
            Cluster clusterB = clusters.get(b);
            List<DataPoint> dpA = clusterA.getDataPoints();
            List<DataPoint> dpB = clusterB.getDataPoints();
            for (DataPoint dp : dpB) {
                DataPoint tempDp = new DataPoint();
                tempDp.setDataPointName(dp.getDataPointName());
                tempDp.setDimensioin(dp.getDimensioin());
                tempDp.setCluster(clusterA);
                dpA.add(tempDp);
            }
            clusterA.setDataPoints(dpA);
            // List<Cluster> clusters中移除cluster[b]
            clusters.remove(b);
        }
        return clusters;
    }
    // 初始化类簇
    private List<Cluster> initialCluster(List<DataPoint> dataPoints){
        List<Cluster> originalClusters=new ArrayList<Cluster>();
        for(int i=0;i<dataPoints.size();i++){
            DataPoint tempDataPoint=dataPoints.get(i);
            List<DataPoint> tempDataPoints=new ArrayList<DataPoint>();
            tempDataPoints.add(tempDataPoint);
            Cluster tempCluster=new Cluster();
            tempCluster.setClusterName("Cluster "+String.valueOf(i));
            tempCluster.setDataPoints(tempDataPoints);
            tempDataPoint.setCluster(tempCluster);
            originalClusters.add(tempCluster);
        }
        return originalClusters;
    }

    //计算两个样本点之间的欧几里得距离
    private double getDistance(DataPoint dpA,DataPoint dpB){
        double distance=0;
        double[] dimA = dpA.getDimensioin();
        double[] dimB = dpB.getDimensioin();
        if (dimA.length == dimB.length) {
            for (int i = 0; i < dimA.length; i++) {
                double temp=Math.pow((dimA[i]-dimB[i]),2);
                distance=distance+temp;
            }
            distance=Math.pow(distance, 0.5);
        }
        return distance;
    }

    /**
     * 从文件读取信息
     * @param filePath 文件路径
     */
    public void getDataFromFile(String filePath){

        try {
            FileInputStream in=new FileInputStream(filePath);
            BufferedReader reader=new BufferedReader(new InputStreamReader(in));
            String tmp;
            int i=0;
            while ((tmp=reader.readLine())!=null){
                String tmpArra[]=tmp.split("\t");
                double[] tmpDouble=new double[tmpArra.length];
                for(int j=1;j<tmpArra.length;j++)
                {
                    tmpDouble[j-1]=Double.parseDouble(tmpArra[j]);
                }
                dataPoints.add(new DataPoint(tmpDouble,tmpArra[0]));
                i++;
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args){
        long startTime=System.currentTimeMillis();
        int clusterNum=3; //类簇数
        ClusterCalculate ca=new ClusterCalculate();
        ca.getDataFromFile("C:\\Users\\TeenTeam\\Desktop\\大数据\\data.txt");
        List<Cluster> clusters=ca.startAnalysis(ca.dataPoints, clusterNum);
        for(Cluster cl:clusters){
            System.out.println("------簇名称为："+cl.getClusterName()+"------");
            List<DataPoint> tempDps=cl.getDataPoints();
            Map <String ,Integer> mapName=new HashMap<String, Integer>();
            for(DataPoint tmpPoint:tempDps){
                if(mapName.get(tmpPoint.getDataPointName())==null)
                    mapName.put(tmpPoint.getDataPointName(),1);
                else mapName.put(tmpPoint.getDataPointName(),(Integer) mapName.get(tmpPoint.getDataPointName()) +1);
            }
            for(String key:mapName.keySet()){
                System.out.println(key+":\t"+mapName.get(key));
            }
            mapName.clear();

        }
        System.out.println("所用的时间为："+(System.currentTimeMillis()-startTime)+"毫秒");
    }
}
